//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using OpenLS.Chart.UI.Internals;
using OpenLS.UI.Internals;


namespace OpenLS.Chart.UI
{
    public class ValueAxisPanel : Panel
    {
        protected override Size ArrangeOverride(Size finalSize)
        {
            AxisOrientation axisOrientation = GetValueAxisOrientation(this);
            Orientation orientation = Orientation;
            TickLabelPosition p = TickLabelPosition;
            if (p == TickLabelPosition.None)
            {
                foreach (UIElement e in InternalChildren)
                    e.Arrange(new Rect(0, 0, 0, 0));
                return base.ArrangeOverride(finalSize);
            }
            ValueAxisProjector projector;
            var rounder = new LayoutRounder(this);
            if (orientation == Orientation.Horizontal)
                projector = new ValueAxisProjector(Minimum, Maximum, 0, finalSize.Width, axisOrientation);
            else
                projector = new ValueAxisProjector(Minimum, Maximum, finalSize.Height, 0,  axisOrientation);
            foreach (UIElement e in InternalChildren)
            {
                Size sz;
                Point pt;
                if (orientation == Orientation.Vertical)
                {
                    sz = new Size(finalSize.Width, e.DesiredSize.Height);
                    double offset;
                    switch (p)
                    {
                        case TickLabelPosition.Low :
                            offset = sz.Height;
                            break;
                        case TickLabelPosition.High:
                            offset = 0;
                            break;
                            default:
                            offset = sz.Height/2;
                            break;
                    }
                    pt = new Point(0, projector.GetValue(GetValue(e)) - offset);
                }
                else
                {
                    sz = new Size(e.DesiredSize.Width, finalSize.Height);
                    double offset;
                    switch (p)
                    {
                        case TickLabelPosition.Low:
                            offset = sz.Width;
                            break;
                        case TickLabelPosition.High:
                            offset = 0;
                            break;
                        default:
                            offset = sz.Width / 2;
                            break;
                    }

                    //pt = new Point(GetScreenPosition(GetValue(e), Minimum, Maximum, 0, finalSize.Width, axisOrientation) - offset, 0);
                    pt = new Point(projector.GetValue(GetValue(e)) - offset, 0);

                }
               // pt = rounder.RoundPoint(pt);
                e.Arrange(rounder.RoundRect(new Rect(pt, sz)));
            }
            return base.ArrangeOverride(finalSize);
        }


        ///<summary>
        /// Get or set the position of the tick labels
        ///</summary>
        public TickLabelPosition TickLabelPosition
        {
            get { return (TickLabelPosition)GetValue(TickLabelPositionProperty); }
            set { SetValue(TickLabelPositionProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TickLabelPosition.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TickLabelPositionProperty =
            DependencyProperty.Register("TickLabelPosition", typeof(TickLabelPosition), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(TickLabelPosition.NextTo, FrameworkPropertyMetadataOptions.AffectsArrange ));


        protected override Size MeasureOverride(Size availableSize)
        {
            bool isHorizontal = Orientation== Orientation.Horizontal;
            var result = new Size();
            foreach (UIElement e in InternalChildren)
            {
                e.Measure(availableSize);
                if (isHorizontal)
                {
                    result.Width += e.DesiredSize.Width;
                    result.Height = Math.Max(result.Height, e.DesiredSize.Height);
                }
                else
                {
                    result.Height += e.DesiredSize.Height;
                    result.Width = Math.Max(result.Width, e.DesiredSize.Width);
                }
            }
            result = new Size(Math.Min(availableSize.Width, result.Width), Math.Min(availableSize.Height, result.Height));
            return result;
        }

       /* internal static double GetScreenPosition(double value, double minValue, double maxValue, double screenMin, double screenMax, AxisOrientation orientation)
        {
            if (maxValue == minValue)
                return screenMin;
            switch (orientation)
            {
                case AxisOrientation.MinimumToMaximum:
                    return screenMin + (screenMax - screenMin) * ((value - minValue) / (maxValue - minValue));
                case AxisOrientation.MaximumToMinimum:
                    return GetScreenPosition(value, minValue, maxValue, screenMax, screenMin, AxisOrientation.MinimumToMaximum);
                default: throw new NotSupportedException();

            }
        }*/
        public static double GetValue(DependencyObject obj)
        {
            return (double)obj.GetValue(ValueProperty);
        }

        public static void SetValue(DependencyObject obj, double value)
        {
            obj.SetValue(ValueProperty, value);
        }

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.RegisterAttached("Value", typeof(double), typeof(FrameworkElement), new UIPropertyMetadata(0.0));



        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Minimum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(0.0,FrameworkPropertyMetadataOptions.AffectsArrange));



        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Maximum.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(1.0,FrameworkPropertyMetadataOptions.AffectsArrange));
            //\\AxisElement.MaximumProperty.AddOwner(typeof(ValueAxisPanel));





        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(System.Windows.Controls.Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure| FrameworkPropertyMetadataOptions.AffectsArrange));


        /*public static Orientation GetOrientation(DependencyObject obj)
        {
            return (Orientation)obj.GetValue(OrientationProperty);
        }

        public static void SetOrientation(DependencyObject obj, Orientation value)
        {
            obj.SetValue(OrientationProperty, value);
        }

        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.RegisterAttached("Orientation", typeof(Orientation), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.Inherits));
        */


/*        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty OrientationProperty =
            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsArrange));


        */


        public static AxisOrientation GetValueAxisOrientation(DependencyObject obj)
        {
            return (AxisOrientation)obj.GetValue(ValueAxisOrientationProperty);
        }

        public static void SetValueAxisOrientation(DependencyObject obj, AxisOrientation value)
        {
            obj.SetValue(ValueAxisOrientationProperty, value);
        }

        // Using a DependencyProperty as the backing store for AxisOrientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueAxisOrientationProperty =
            DependencyProperty.RegisterAttached("ValueAxisOrientation", typeof(AxisOrientation), typeof(FrameworkElement), new FrameworkPropertyMetadata(AxisOrientation.MinimumToMaximum,FrameworkPropertyMetadataOptions.AffectsArrange));


        /*
        public AxisOrientation AxisOrientation
        {
            get { return (AxisOrientation)GetValue(AxisOrientationProperty); }
            set { SetValue(AxisOrientationProperty, value); }
        }

        // Using a DependencyProperty as the backing store for AxisOrientation.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty AxisOrientationProperty =
            DependencyProperty.Register("AxisOrientation", typeof(AxisOrientation), typeof(ValueAxisPanel), new FrameworkPropertyMetadata(AxisOrientation.MinimumToMaximum, FrameworkPropertyMetadataOptions.AffectsArrange));

        */

    }
}